//==================================================
//   D Flip-Flop
//==================================================
module D_FF(Q,D,iCLK,iReset);
    
    input       iCLK   ,//input Clock
                iReset ;//input reset signal
    
    input       D      ;//input Data
    output reg  Q      ;//output Data
    
    always@(posedge iCLK) begin
       
       if(iReset)
              Q<=1'd0   ; 
       else
              Q<=D      ;
    end
  
    
endmodule


module D_FF_8bit(Q,D,iCLK,iReset);
    
    input       iCLK   ,//input Clock
                iReset ;//input reset signal
    
    input      [7:0] D      ;//input Data
    output reg [7:0] Q      ;//output Data
    
    always@(posedge iCLK) begin
       
       if(iReset)
              Q<=8'd0   ; 
       else
              Q<=D      ;
    end
  
    
endmodule

module D_FF_16bit(Q,D,iCLK,iReset);
    
    input      iCLK   ,//input Clock
               iReset ;//input reset signal
                          
    input      [15:0]  D      ;//input Data
    output reg [15:0]  Q      ;//output Data
    
    always@(posedge iCLK) begin
       
       if(iReset)
              Q<=16'd0   ; 
       else
              Q<=D      ;
    end
  
    
endmodule
//==================================================
//  Half Adder & Carry Look Ahead Adder
//==================================================
module HA(Cout,SUM,A,B);
    
    input    A,B        ;
    output   SUM, Cout  ;
    
    and a1(Cout,A,B);
    xor x1(SUM,A,B);
    
endmodule


module CLA(oCin,SUM,iA,iB,iCin);
    
    input    iA,iB,iCin   ;
    output   oCin,SUM     ;
    
    wire   w1   ;
   
    and a1(oG,iA,iB);
    or o1(oP,iA,iB);
   
    xor x1(SUM,iA,iB,iCin); 
    and a2(w1,oP,iCin);
    or  o2(oCin,w1,oG);
    
endmodule 

module CLA12(oSUM,iA,iB,iCin);
    
    input   [11:0]   iA,iB,iCin ;
    output  [12:0]   oSUM    ;
    
    wire    [10:0]   oCin   ;
    
    CLA  cla0( oCin[0], oSUM[0], iA[0], iB[0], iCin   );
    CLA  cla1( oCin[1], oSUM[1], iA[1], iB[1], oCin[0]);
    CLA  cla2( oCin[2], oSUM[2], iA[2], iB[2], oCin[1]);
    CLA  cla3( oCin[3], oSUM[3], iA[3], iB[3], oCin[2]);
    CLA  cla4( oCin[4], oSUM[4], iA[4], iB[4], oCin[3]);
    CLA  cla5( oCin[5], oSUM[5], iA[5], iB[5], oCin[4]);
    CLA  cla6( oCin[6], oSUM[6], iA[6], iB[6], oCin[5]);
    CLA  cla7( oCin[7], oSUM[7], iA[7], iB[7], oCin[6]);
    CLA  cla8( oCin[8], oSUM[8], iA[8], iB[8], oCin[7]);
    CLA  cla9( oCin[9], oSUM[9], iA[9], iB[9], oCin[8]);
    CLA cla10(oCin[10],oSUM[10],iA[10],iB[10], oCin[9]);
    CLA cla11(oSUM[12],oSUM[11],iA[11],iB[11],oCin[10]);
        
endmodule
//==================================================
//   Booth Encoder & Decoder
//==================================================

module Booth_Encoder(Single,Double,Negate,iX);
    
    input       [2:0] iX                   ;
    output reg        Single,Double,Negate ;
    
    always@(*)begin
       case(iX)
           3'd0 :{Single,Double,Negate} <= 3'b000 ;
           3'd1 :{Single,Double,Negate} <= 3'b100 ;
           3'd2 :{Single,Double,Negate} <= 3'b100 ;
           3'd3 :{Single,Double,Negate} <= 3'b010 ;
           3'd4 :{Single,Double,Negate} <= 3'b011 ;
           3'd5 :{Single,Double,Negate} <= 3'b101 ;
           3'd6 :{Single,Double,Negate} <= 3'b101 ;
           3'd7 :{Single,Double,Negate} <= 3'b001 ;
         default:{Single,Double,Negate} <= 3'b000 ;
                      
        endcase
    
    end
endmodule

module Booth_Encoder_3bit(SNG,DBL,NEG,iX);
       
       input [7:0]   iX            ;
       output[3:0]   SNG,DBL,NEG   ;
       
       Booth_Encoder ecd0(SNG[0],DBL[0],NEG[0],{iX[1:0],1'b0});
       Booth_Encoder ecd1(SNG[1],DBL[1],NEG[1],iX[3:1]);
       Booth_Encoder ecd2(SNG[2],DBL[2],NEG[2],iX[5:3]);
       Booth_Encoder ecd3(SNG[3],DBL[3],NEG[3],iX[7:5]);
    
endmodule

module Booth_Decoder(PR,SNG,DBL,NEG,iY1,iY0);

   output PR                   ;
   input  SNG,DBL,NEG,iY1,iY0  ;
   
   wire [2:0] W;
   
   nand n1(W[0],SNG,iY1);
   nand n2(W[1],DBL,iY0);
   nand n3(W[2],W[0],W[1]);
   xor  x1(PR,W[2],NEG);
   
endmodule

module Booth_Decoder_8bit(PR,iY,SNG,DBL,NEG);
    
    input         SNG,DBL,NEG   ;
    input [7:0]   iY            ;
    
    output [8:0]  PR            ;
    
    wire   [8:0]   wPR,wwPR      ;
      
    Booth_Decoder  bdec0(wPR[0],SNG,DBL,NEG,iY[0],{1'b0});
    Booth_Decoder  bdec1(wPR[1],SNG,DBL,NEG,iY[1],iY[0]);
    Booth_Decoder  bdec2(wPR[2],SNG,DBL,NEG,iY[2],iY[1]);
    Booth_Decoder  bdec3(wPR[3],SNG,DBL,NEG,iY[3],iY[2]);
    Booth_Decoder  bdec4(wPR[4],SNG,DBL,NEG,iY[4],iY[3]);
    Booth_Decoder  bdec5(wPR[5],SNG,DBL,NEG,iY[5],iY[4]);
    Booth_Decoder  bdec6(wPR[6],SNG,DBL,NEG,iY[6],iY[5]);
    Booth_Decoder  bdec7(wPR[7],SNG,DBL,NEG,iY[7],iY[6]);
    Booth_Decoder  bdec8(wPR[8],SNG,DBL,NEG,iY[7],iY[7]);
       
    HA  ha0 (wwPR[0],PR[0],wPR[0],    NEG);   
    HA  ha1 (wwPR[1],PR[1],wPR[1],wwPR[0]);
    HA  ha2 (wwPR[2],PR[2],wPR[2],wwPR[1]); 
    HA  ha3 (wwPR[3],PR[3],wPR[3],wwPR[2]); 
    HA  ha4 (wwPR[4],PR[4],wPR[4],wwPR[3]); 
    HA  ha5 (wwPR[5],PR[5],wPR[5],wwPR[4]); 
    HA  ha6 (wwPR[6],PR[6],wPR[6],wwPR[5]); 
    HA  ha7 (wwPR[7],PR[7],wPR[7],wwPR[6]); 
    HA  ha8 (wwPR[8],PR[8],wPR[8],wwPR[7]);  
    
endmodule

//==================================================
//   Booth Multilplier
//==================================================

module   booth(iClk,
               iReset,
               iReady,
               oDone,
               iMultiplier,
               iMultiplicand,
               oProduct
               );
               
   input         iClk          ,//input clock
                 iReset        ,//reset signal
                 iReady        ;//indicates input are ready
                 
   input  [7:0]  iMultiplier   ,//8-bit multiplicand[7:0]
                 iMultiplicand ;//8-bit multiplier[7:0]
   
   output        oDone        ;//indicates that the result ready
   output [15:0] oProduct     ;//16-bit product[15:0]
   
   wire   [7:0]   d_ME,d_MC,p_ME,p_MC  ;
   wire   [18:0]  PRD         ;
   wire           d_ird       ;
   
   wire   [3:0]   SNG,DBL,NEG      ;
   wire   [8:0]   PR0,PR1,PR2,PR3  ;
   wire   [12:0]  oCLA1,oCLA2,oCLA3;
   wire   [11:0]  sign_ex_PR0,
                  sign_ex_PR1,
                  sign_ex_PR2,
                  sign_ex_PR3,
                  sign_ex_PR4,
                  sign_ex_PR5;
   
   wire iCLK;
   assign iCLK=iClk;
   
   D_FF_8bit in1(d_ME,iMultiplier  ,iCLK,iReset);
   D_FF_8bit in2(d_MC,iMultiplicand,iCLK,iReset);
   D_FF     irdy(d_ird,iReady      ,iCLK,iReset);
   
   and a1[7:0](p_MC,d_MC,d_ird);
   and a2[7:0](p_ME,d_ME,d_ird);
   
   Booth_Encoder_3bit enc(SNG,DBL,NEG,p_ME);
  
   Booth_Decoder_8bit dec0(PR0,p_MC,SNG[0],DBL[0],NEG[0]);
   Booth_Decoder_8bit dec1(PR1,p_MC,SNG[1],DBL[1],NEG[1]);
   Booth_Decoder_8bit dec2(PR2,p_MC,SNG[2],DBL[2],NEG[2]);
   Booth_Decoder_8bit dec3(PR3,p_MC,SNG[3],DBL[3],NEG[3]);
      
   assign sign_ex_PR0 = {{3{PR1[8]}},PR1} ;
   assign sign_ex_PR1 = {{3{PR2[8]}},PR2} ;
   assign sign_ex_PR2 = {{3{PR3[8]}},PR3} ;
   
   assign sign_ex_PR3 = {{5{PR0[8]}},PR0[8:2]} ;
   assign sign_ex_PR4 = {{5{oCLA1[8]}},oCLA1[8:2]} ;
   assign sign_ex_PR5 = {{5{oCLA2[8]}},oCLA2[8:2]} ;
   
   CLA12 cla0(oCLA1,sign_ex_PR0,sign_ex_PR3,1'b0);
   CLA12 cla1(oCLA2,sign_ex_PR1,sign_ex_PR4,1'b0);
   CLA12 cla2(oCLA3,sign_ex_PR2,sign_ex_PR5,1'b0);
   
   assign PRD[1:0] = PR0[1:0]   ;
   assign PRD[3:2] = oCLA1[1:0] ;
   assign PRD[5:4] = oCLA2[1:0] ;
   assign PRD[18:6]= oCLA3      ;
   
   D_FF      ordy(oDone   ,     d_ird,iCLK,iReset);
   D_FF_16bit out(oProduct, PRD[15:0],iCLK,iReset); 
               
endmodule
